D:\a\tools.proto\tools.proto\compiler\src\compiler\structure.rs
Line | Count | Source |
1 | | // Copyright (c) 2025, BlockProject 3D |
2 | | // |
3 | | // All rights reserved. |
4 | | // |
5 | | // Redistribution and use in source and binary forms, with or without modification, |
6 | | // are permitted provided that the following conditions are met: |
7 | | // |
8 | | // * Redistributions of source code must retain the above copyright notice, |
9 | | // this list of conditions and the following disclaimer. |
10 | | // * Redistributions in binary form must reproduce the above copyright notice, |
11 | | // this list of conditions and the following disclaimer in the documentation |
12 | | // and/or other materials provided with the distribution. |
13 | | // * Neither the name of BlockProject 3D nor the names of its contributors |
14 | | // may be used to endorse or promote products derived from this software |
15 | | // without specific prior written permission. |
16 | | // |
17 | | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
18 | | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
19 | | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
20 | | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
21 | | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
22 | | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
23 | | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
24 | | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
25 | | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
26 | | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
27 | | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | | |
29 | | use crate::compiler::error::Error; |
30 | | use crate::compiler::r#enum::Enum; |
31 | | use crate::compiler::util::objects::name_index; |
32 | | use crate::compiler::util::try2; |
33 | | use crate::compiler::util::types::Name; |
34 | | use crate::compiler::Protocol; |
35 | | use crate::model::protocol::{Description, Endianness}; |
36 | | use crate::model::structure::{SimpleType, StructFieldRaw, StructFieldView}; |
37 | | use bp3d_debug::trace; |
38 | | use std::cell::Cell; |
39 | | use std::fmt::{Display, Formatter}; |
40 | | use std::rc::Rc; |
41 | | |
42 | | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
43 | | pub enum FixedFieldType { |
44 | | Int8, |
45 | | Int16, |
46 | | Int32, |
47 | | Int64, |
48 | | UInt8, |
49 | | UInt16, |
50 | | UInt32, |
51 | | UInt64, |
52 | | Float32, |
53 | | Float64, |
54 | | Bool, |
55 | | } |
56 | | |
57 | | impl FixedFieldType { |
58 | 0 | pub fn get_aligned_bit_size(&self) -> usize { |
59 | 0 | match self { |
60 | 0 | FixedFieldType::Int8 => 8, |
61 | 0 | FixedFieldType::Int16 => 16, |
62 | 0 | FixedFieldType::Int32 => 32, |
63 | 0 | FixedFieldType::Int64 => 64, |
64 | 0 | FixedFieldType::UInt8 => 8, |
65 | 0 | FixedFieldType::UInt16 => 16, |
66 | 0 | FixedFieldType::UInt32 => 32, |
67 | 0 | FixedFieldType::UInt64 => 64, |
68 | 0 | FixedFieldType::Float32 => 32, |
69 | 0 | FixedFieldType::Float64 => 64, |
70 | 0 | FixedFieldType::Bool => 8 |
71 | | } |
72 | 0 | } |
73 | | |
74 | 0 | pub fn is_unsigned(&self) -> bool { |
75 | 0 | match self { |
76 | 0 | FixedFieldType::Int8 => false, |
77 | 0 | FixedFieldType::Int16 => false, |
78 | 0 | FixedFieldType::Int32 => false, |
79 | 0 | FixedFieldType::Int64 => false, |
80 | 0 | FixedFieldType::UInt8 => true, |
81 | 0 | FixedFieldType::UInt16 => true, |
82 | 0 | FixedFieldType::UInt32 => true, |
83 | 0 | FixedFieldType::UInt64 => true, |
84 | 0 | FixedFieldType::Float32 => false, |
85 | 0 | FixedFieldType::Float64 => false, |
86 | 0 | FixedFieldType::Bool => false |
87 | | } |
88 | 0 | } |
89 | | |
90 | 6 | pub fn is_signed(&self) -> bool { |
91 | 6 | match self { |
92 | 0 | FixedFieldType::Int8 => true, |
93 | 0 | FixedFieldType::Int16 => true, |
94 | 0 | FixedFieldType::Int32 => true, |
95 | 0 | FixedFieldType::Int64 => true, |
96 | 3 | FixedFieldType::UInt8 => false, |
97 | 0 | FixedFieldType::UInt16 => false, |
98 | 3 | FixedFieldType::UInt32 => false, |
99 | 0 | FixedFieldType::UInt64 => false, |
100 | 0 | FixedFieldType::Float32 => false, |
101 | 0 | FixedFieldType::Float64 => false, |
102 | 0 | FixedFieldType::Bool => false, |
103 | | } |
104 | 6 | } |
105 | | } |
106 | | |
107 | | impl Display for FixedFieldType { |
108 | 711 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
109 | 711 | match self { |
110 | 0 | FixedFieldType::Int8 => f.write_str("Int8"), |
111 | 0 | FixedFieldType::Int16 => f.write_str("Int16"), |
112 | 0 | FixedFieldType::Int32 => f.write_str("Int32"), |
113 | 0 | FixedFieldType::Int64 => f.write_str("Int64"), |
114 | 343 | FixedFieldType::UInt8 => f.write_str("UInt8"), |
115 | 77 | FixedFieldType::UInt16 => f.write_str("UInt16"), |
116 | 171 | FixedFieldType::UInt32 => f.write_str("UInt32"), |
117 | 108 | FixedFieldType::UInt64 => f.write_str("UInt64"), |
118 | 12 | FixedFieldType::Float32 => f.write_str("Float32"), |
119 | 0 | FixedFieldType::Float64 => f.write_str("Float64"), |
120 | 0 | FixedFieldType::Bool => f.write_str("Bool"), |
121 | | } |
122 | 711 | } |
123 | | } |
124 | | |
125 | 682 | fn map_numeric( |
126 | 682 | ty: SimpleType, |
127 | 682 | signed: FixedFieldType, |
128 | 682 | unsigned: FixedFieldType, |
129 | 682 | float: FixedFieldType, |
130 | 682 | ) -> Option<FixedFieldType> { |
131 | 682 | match ty { |
132 | 84 | SimpleType::Signed => Some(signed), |
133 | 586 | SimpleType::Unsigned => Some(unsigned), |
134 | 12 | SimpleType::Float => Some(float), |
135 | 0 | _ => None, |
136 | | } |
137 | 682 | } |
138 | | |
139 | | impl FixedFieldType { |
140 | 206 | pub fn get_byte_size(&self) -> usize { |
141 | 206 | match self { |
142 | 0 | FixedFieldType::Int8 => 1, |
143 | 0 | FixedFieldType::Int16 => 2, |
144 | 0 | FixedFieldType::Int32 => 4, |
145 | 0 | FixedFieldType::Int64 => 8, |
146 | 95 | FixedFieldType::UInt8 => 1, |
147 | 24 | FixedFieldType::UInt16 => 2, |
148 | 51 | FixedFieldType::UInt32 => 4, |
149 | 36 | FixedFieldType::UInt64 => 8, |
150 | 0 | FixedFieldType::Float32 => 4, |
151 | 0 | FixedFieldType::Float64 => 8, |
152 | 0 | FixedFieldType::Bool => 1, |
153 | | } |
154 | 206 | } |
155 | | |
156 | 18 | pub fn from_min_max_value(min_value: isize, max_value: isize) -> Result<Self, Error> { |
157 | 18 | match min_value < 0 { |
158 | | true => { |
159 | 6 | let bit_size = if max_value > i32::MAX as isize || min_value < i32::MIN as isize { Branch (159:35): [True: 0, False: 6]
Branch (159:68): [True: 0, False: 6]
Branch (159:35): [Folded - Ignored]
Branch (159:68): [Folded - Ignored]
|
160 | 0 | 64 |
161 | 6 | } else if max_value > i16::MAX as isize || min_value < i16::MIN as isize { Branch (161:27): [True: 0, False: 6]
Branch (161:60): [True: 0, False: 6]
Branch (161:27): [Folded - Ignored]
Branch (161:60): [Folded - Ignored]
|
162 | 0 | 32 |
163 | 6 | } else if max_value > i8::MAX as isize || min_value < i8::MIN as isize { Branch (163:27): [True: 0, False: 6]
Branch (163:59): [True: 0, False: 6]
Branch (163:27): [Folded - Ignored]
Branch (163:59): [Folded - Ignored]
|
164 | 0 | 16 |
165 | | } else { |
166 | 6 | 8 |
167 | | }; |
168 | 6 | Self::from_model(StructFieldRaw::Signed { bits: bit_size }) |
169 | | } |
170 | | false => { |
171 | 12 | let bit_size = if max_value > u32::MAX as isize { Branch (171:35): [True: 0, False: 12]
Branch (171:35): [Folded - Ignored]
|
172 | 0 | 64 |
173 | 12 | } else if max_value > u16::MAX as isize { Branch (173:27): [True: 0, False: 12]
Branch (173:27): [Folded - Ignored]
|
174 | 0 | 32 |
175 | 12 | } else if max_value > u8::MAX as isize { Branch (175:27): [True: 0, False: 12]
Branch (175:27): [Folded - Ignored]
|
176 | 0 | 16 |
177 | | } else { |
178 | 12 | 8 |
179 | | }; |
180 | 12 | Self::from_model(StructFieldRaw::Unsigned { bits: bit_size }) |
181 | | } |
182 | | } |
183 | 18 | } |
184 | | |
185 | 88 | pub fn from_max_value(max_value: usize) -> Result<Self, Error> { |
186 | 88 | let bit_size = if max_value > u32::MAX as usize { Branch (186:27): [True: 0, False: 88]
Branch (186:27): [Folded - Ignored]
|
187 | 0 | 64 |
188 | 88 | } else if max_value > u16::MAX as usize { Branch (188:19): [True: 12, False: 76]
Branch (188:19): [Folded - Ignored]
|
189 | 12 | 32 |
190 | 76 | } else if max_value > u8::MAX as usize { Branch (190:19): [True: 6, False: 70]
Branch (190:19): [Folded - Ignored]
|
191 | 6 | 16 |
192 | | } else { |
193 | 70 | 8 |
194 | | }; |
195 | 88 | Self::from_model(StructFieldRaw::Unsigned { bits: bit_size }) |
196 | 88 | } |
197 | | |
198 | 749 | pub fn from_model(ty1: StructFieldRaw) -> Result<Self, Error> { |
199 | 749 | let motherfuckingrust = ty1.clone(); |
200 | 749 | let ty = ty1.get_simple_type(); |
201 | 749 | let bit_size = ty1.get_bit_size(); |
202 | 749 | if ty == SimpleType::Boolean { Branch (202:12): [True: 36, False: 713]
Branch (202:12): [Folded - Ignored]
|
203 | 36 | Ok(Self::Bool) |
204 | 713 | } else if ty == SimpleType::Float && bit_size == 3242 { Branch (204:19): [True: 42, False: 671]
Branch (204:46): [True: 18, False: 24]
Branch (204:19): [Folded - Ignored]
Branch (204:46): [Folded - Ignored]
|
205 | 18 | Ok(Self::Float32) |
206 | 695 | } else if ty == SimpleType::Float && bit_size == 6424 { Branch (206:19): [True: 24, False: 671]
Branch (206:46): [True: 12, False: 12]
Branch (206:19): [Folded - Ignored]
Branch (206:46): [Folded - Ignored]
|
207 | 12 | Ok(Self::Float64) |
208 | 683 | } else if bit_size > 32 && bit_size <= 6490 { Branch (208:19): [True: 90, False: 593]
Branch (208:36): [True: 90, False: 0]
Branch (208:19): [Folded - Ignored]
Branch (208:36): [Folded - Ignored]
|
209 | 90 | map_numeric(ty, Self::Int64, Self::UInt64, Self::Float64).ok_or(Error::UnsupportedType(motherfuckingrust)) |
210 | 593 | } else if bit_size > 16 && bit_size <= 32151 { Branch (210:19): [True: 151, False: 442]
Branch (210:36): [True: 151, False: 0]
Branch (210:19): [Folded - Ignored]
Branch (210:36): [Folded - Ignored]
|
211 | 151 | map_numeric(ty, Self::Int32, Self::UInt32, Self::Float64).ok_or(Error::UnsupportedType(motherfuckingrust)) |
212 | 442 | } else if bit_size > 8 && bit_size <= 1672 { Branch (212:19): [True: 72, False: 370]
Branch (212:35): [True: 72, False: 0]
Branch (212:19): [Folded - Ignored]
Branch (212:35): [Folded - Ignored]
|
213 | 72 | map_numeric(ty, Self::Int16, Self::UInt16, Self::Float32).ok_or(Error::UnsupportedType(motherfuckingrust)) |
214 | 370 | } else if bit_size > 0 && bit_size <= 8369 { Branch (214:19): [True: 369, False: 1]
Branch (214:35): [True: 369, False: 0]
Branch (214:19): [Folded - Ignored]
Branch (214:35): [Folded - Ignored]
|
215 | 369 | map_numeric(ty, Self::Int8, Self::UInt8, Self::Float32).ok_or(Error::UnsupportedType(motherfuckingrust)) |
216 | | } else { |
217 | 1 | Err(Error::UnsupportedBitSize(bit_size)) |
218 | | } |
219 | 749 | } |
220 | | } |
221 | | |
222 | | #[derive(Clone, Debug)] |
223 | | pub struct Location { |
224 | | pub byte_offset: usize, |
225 | | pub bit_offset: usize, |
226 | | pub byte_size: usize, |
227 | | pub bit_size: usize, |
228 | | } |
229 | | |
230 | | impl Display for Location { |
231 | 708 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
232 | 708 | write!( |
233 | 708 | f, |
234 | 708 | "bytes {}..{}, bits {}..{}", |
235 | | self.byte_offset, |
236 | 708 | self.byte_offset + self.byte_size, |
237 | | self.bit_offset, |
238 | 708 | self.bit_offset + self.bit_size |
239 | | ) |
240 | 708 | } |
241 | | } |
242 | | |
243 | | impl Location { |
244 | 361 | fn from_model(bit_size: usize, bit_offset: usize) -> Self { |
245 | 361 | let byte_offset = bit_offset / 8; |
246 | | Self { |
247 | 361 | byte_offset, |
248 | 361 | bit_offset: bit_offset - byte_offset * 8, |
249 | 361 | bit_size, |
250 | 361 | byte_size: if bit_size % 8 != 0 { Branch (250:27): [True: 96, False: 265]
Branch (250:27): [Folded - Ignored]
|
251 | 96 | (bit_size / 8) + 1 |
252 | | } else { |
253 | 265 | bit_size / 8 |
254 | | }, |
255 | | } |
256 | 361 | } |
257 | | } |
258 | | |
259 | | #[derive(Clone, Debug)] |
260 | | pub enum FieldRaw { |
261 | | /// Apply a raw C-like cast (used for unsigned > signed and unsigned > float of same bit size). |
262 | | Transmute, |
263 | | |
264 | | /// Apply a unsigned > signed cast on a non T-aligned value, |
265 | | /// the maximum positive value is passed in. |
266 | | SignedCast(usize), |
267 | | |
268 | | /// Don't do anything special, just return the raw value. |
269 | | None, |
270 | | } |
271 | | |
272 | | impl FieldRaw { |
273 | 39 | pub fn is_none(&self) -> bool { |
274 | 39 | matches!0 (self, Self::None) |
275 | 39 | } |
276 | | |
277 | 327 | fn from_model(ty: SimpleType, bit_size: usize) -> FieldRaw { |
278 | 327 | if ty == SimpleType::Float && bit_size != 3242 && bit_size != 6424 { Branch (278:12): [True: 42, False: 285]
Branch (278:39): [True: 24, False: 18]
Branch (278:57): [True: 12, False: 12]
Branch (278:12): [Folded - Ignored]
Branch (278:39): [Folded - Ignored]
Branch (278:57): [Folded - Ignored]
|
279 | 12 | return FieldRaw::None; |
280 | 315 | } |
281 | 315 | if ty == SimpleType::Signed && bit_size != 878 && bit_size != 1666 && bit_size != 3254 && bit_size != 6436 { Branch (281:12): [True: 78, False: 237]
Branch (281:40): [True: 66, False: 12]
Branch (281:57): [True: 54, False: 12]
Branch (281:75): [True: 36, False: 18]
Branch (281:93): [True: 30, False: 6]
Branch (281:12): [Folded - Ignored]
Branch (281:40): [Folded - Ignored]
Branch (281:57): [Folded - Ignored]
Branch (281:75): [Folded - Ignored]
Branch (281:93): [Folded - Ignored]
|
282 | 30 | let max_value = 1 << (bit_size - 1); |
283 | 30 | FieldRaw::SignedCast(max_value - 1) |
284 | 285 | } else if ty == SimpleType::Unsigned { Branch (284:19): [True: 171, False: 114]
Branch (284:19): [Folded - Ignored]
|
285 | 171 | FieldRaw::None |
286 | | } else { |
287 | 114 | FieldRaw::Transmute |
288 | | } |
289 | 327 | } |
290 | | } |
291 | | |
292 | | #[derive(Clone, Debug)] |
293 | | pub enum FieldView { |
294 | | /// Apply a float view based on an affine transformation function. |
295 | | Float { a: f64, b: f64, a_inv: f64, b_inv: f64 }, |
296 | | |
297 | | /// Apply an enum view. |
298 | | Enum(Rc<Enum>), |
299 | | |
300 | | /// Don't do anything special, just return the raw value. |
301 | | None, |
302 | | } |
303 | | |
304 | | impl FieldView { |
305 | 331 | fn from_model( |
306 | 331 | proto: &Protocol, |
307 | 331 | ty: SimpleType, |
308 | 331 | bit_size: usize, |
309 | 331 | value: Option<StructFieldView>, |
310 | 331 | ) -> Result<Self, Error> { |
311 | 33 | match value { |
312 | 19 | Some(StructFieldView::Enum { name }) => { |
313 | 19 | if ty != SimpleType::Unsigned && ty != SimpleType::Signed7 { Branch (313:20): [True: 7, False: 12]
Branch (313:50): [True: 1, False: 6]
Branch (313:20): [Folded - Ignored]
Branch (313:50): [Folded - Ignored]
|
314 | 1 | return Err(Error::UnsupportedViewType(ty)); |
315 | 18 | } |
316 | 18 | let r = proto.enums.get(&name).ok_or(Error::UndefinedReference(name))?0 ; |
317 | 18 | Ok(FieldView::Enum(r.clone())) |
318 | | } |
319 | 7 | Some(StructFieldView::FloatRange { min, max }) => { |
320 | 7 | if ty != SimpleType::Float { Branch (320:20): [True: 1, False: 6]
Branch (320:20): [Folded - Ignored]
|
321 | 1 | return Err(Error::UnsupportedViewType(ty)); |
322 | 6 | } |
323 | 6 | let raw_max: usize = (1 << bit_size) - 1; |
324 | 6 | let a = max / (raw_max as f64); |
325 | 6 | let b = min; |
326 | 6 | let a_inv = 1.0 / a; |
327 | 6 | let b_inv = -b; |
328 | 6 | Ok(FieldView::Float { a, b, a_inv, b_inv }) |
329 | | } |
330 | 7 | Some(StructFieldView::FloatMultiplier { multiplier }) => { |
331 | 7 | if ty != SimpleType::Float { Branch (331:20): [True: 1, False: 6]
Branch (331:20): [Folded - Ignored]
|
332 | 1 | return Err(Error::UnsupportedViewType(ty)); |
333 | 6 | } |
334 | 6 | let a = multiplier; |
335 | 6 | let b = 0.0; |
336 | 6 | let a_inv = 1.0 / a; |
337 | 6 | let b_inv = 0.0; |
338 | 6 | Ok(FieldView::Float { a, b, a_inv, b_inv }) |
339 | | } |
340 | | None => { |
341 | 298 | if ty == SimpleType::Float && bit_size != 3231 && bit_size != 6413 { Branch (341:20): [True: 31, False: 267]
Branch (341:47): [True: 13, False: 18]
Branch (341:65): [True: 1, False: 12]
Branch (341:20): [Folded - Ignored]
Branch (341:47): [Folded - Ignored]
Branch (341:65): [Folded - Ignored]
|
342 | 1 | return Err(Error::UnsupportedViewType(ty)); |
343 | 297 | } |
344 | 297 | Ok(FieldView::None) |
345 | | } |
346 | | } |
347 | 331 | } |
348 | | } |
349 | | |
350 | | #[derive(Clone, Debug)] |
351 | | pub struct FixedField { |
352 | | pub bits_type: FixedFieldType, |
353 | | pub raw_type: FixedFieldType, |
354 | | pub view_type: FixedFieldType, |
355 | | pub raw: FieldRaw, |
356 | | pub view: FieldView, |
357 | | pub endianness: Endianness, |
358 | | } |
359 | | |
360 | | impl Display for FixedField { |
361 | 600 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
362 | 600 | write!(f, "{}, {} endian", self.bits_type, self.endianness) |
363 | 600 | } |
364 | | } |
365 | | |
366 | | #[derive(Clone, Debug)] |
367 | | pub struct FixedArrayField { |
368 | | pub ty: FixedFieldType, |
369 | | pub array_len: usize, |
370 | | pub endianness: Endianness, |
371 | | pub item_bit_size: usize, |
372 | | } |
373 | | |
374 | | impl Display for FixedArrayField { |
375 | 36 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
376 | 36 | write!(f, "{}[{}], {} endian", self.ty, self.array_len, self.endianness) |
377 | 36 | } |
378 | | } |
379 | | |
380 | | #[derive(Clone, Debug)] |
381 | | pub enum FieldType { |
382 | | Fixed(FixedField), |
383 | | Array(FixedArrayField), |
384 | | Struct(Rc<Structure>), |
385 | | } |
386 | | |
387 | | impl Display for FieldType { |
388 | 708 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
389 | 708 | match self { |
390 | 600 | FieldType::Fixed(v) => v.fmt(f), |
391 | 36 | FieldType::Array(v) => v.fmt(f), |
392 | 72 | FieldType::Struct(v) => f.write_str(v.name()), |
393 | | } |
394 | 708 | } |
395 | | } |
396 | | |
397 | | impl FieldType { |
398 | 401 | pub fn as_fixed(&self) -> Option<&FixedField> { |
399 | 401 | match self { |
400 | 401 | FieldType::Fixed(v) => Some(v), |
401 | 0 | _ => None, |
402 | | } |
403 | 401 | } |
404 | | } |
405 | | |
406 | | #[derive(Clone, Debug)] |
407 | | pub struct Field { |
408 | | pub name: String, |
409 | | pub loc: Location, |
410 | | pub description: Option<Description>, |
411 | | pub ty: FieldType, |
412 | | } |
413 | | |
414 | | impl Display for Field { |
415 | 708 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
416 | 708 | write!(f, "{}: {} ({})", self.name, self.ty, self.loc) |
417 | 708 | } |
418 | | } |
419 | | |
420 | | impl Field { |
421 | 369 | fn from_model( |
422 | 369 | proto: &Protocol, |
423 | 369 | fields: &[Field], |
424 | 369 | mut last_bit_offset: usize, |
425 | 369 | value: crate::model::structure::StructField, |
426 | 369 | ) -> Result<(Self, usize), Error> { |
427 | 369 | if (value.raw.is_none() && value.item_type37 .is_none37 ()) || (value.raw.is_some() && value.item_type332 .is_some332 ()) { Branch (427:13): [True: 37, False: 332]
Branch (427:36): [True: 0, False: 37]
Branch (427:67): [True: 332, False: 37]
Branch (427:90): [True: 0, False: 332]
Branch (427:13): [Folded - Ignored]
Branch (427:36): [Folded - Ignored]
Branch (427:67): [Folded - Ignored]
Branch (427:90): [Folded - Ignored]
|
428 | 0 | return Err(Error::BadFieldType); |
429 | 369 | } |
430 | 369 | let (ty361 , bit_size361 ) = if let Some(info332 ) = value.raw { Branch (430:37): [True: 332, False: 37]
Branch (430:37): [Folded - Ignored]
|
431 | 332 | let array_len = value.array_len.unwrap_or(1); |
432 | 332 | if array_len == 0 { Branch (432:16): [True: 1, False: 331]
Branch (432:16): [Folded - Ignored]
|
433 | 1 | return Err(Error::ZeroArray); |
434 | 331 | } |
435 | 331 | let mut bit_size = info.get_bit_size(); |
436 | 331 | let view327 = FieldView::from_model(proto, info.get_simple_type(), bit_size, value.view)?4 ; |
437 | 327 | let raw = FieldRaw::from_model(info.get_simple_type(), bit_size); |
438 | 327 | bit_size *= array_len; |
439 | 327 | let ty326 = FixedFieldType::from_model(info)?1 ; |
440 | 326 | if array_len > 1 { Branch (440:16): [True: 19, False: 307]
Branch (440:16): [Folded - Ignored]
|
441 | 19 | if (bit_size / array_len) % 8 != 0 { Branch (441:20): [True: 1, False: 18]
Branch (441:20): [Folded - Ignored]
|
442 | 1 | return Err(Error::UnalignedArrayCodec); |
443 | 18 | } |
444 | 18 | ( |
445 | 18 | FieldType::Array(FixedArrayField { |
446 | 18 | endianness: proto.endianness, |
447 | 18 | array_len, |
448 | 18 | ty, |
449 | 18 | item_bit_size: bit_size / array_len, |
450 | 18 | }), |
451 | 18 | bit_size, |
452 | 18 | ) |
453 | | } else { |
454 | 307 | let bits_type = FixedFieldType::from_model(StructFieldRaw::Unsigned { bits: bit_size })?0 ; |
455 | 307 | let raw_type = match (bit_size, ty) { |
456 | 12 | (32, FixedFieldType::Float32) => FixedFieldType::Float32, |
457 | 12 | (64, FixedFieldType::Float64) => FixedFieldType::Float64, |
458 | 6 | (_, FixedFieldType::Float32) => bits_type, |
459 | 6 | (_, FixedFieldType::Float64) => bits_type, |
460 | 271 | _ => ty, |
461 | | }; |
462 | 307 | ( |
463 | 307 | FieldType::Fixed(FixedField { |
464 | 307 | endianness: proto.endianness, |
465 | 307 | bits_type, |
466 | 307 | raw_type, |
467 | 307 | view_type: ty, |
468 | 307 | view, |
469 | 307 | raw, |
470 | 307 | }), |
471 | 307 | bit_size, |
472 | 307 | ) |
473 | | } |
474 | | } else { |
475 | 37 | let item_type = unsafe { value.item_type.unwrap_unchecked() }; |
476 | 37 | let r36 = try2!36 (proto.structs.get(&item_type) => Error::UndefinedReference(item_type)1 ); |
477 | 36 | trace!("Solved reference {} => {:?}", item_type, r); |
478 | 36 | (FieldType::Struct(r.clone()), r.bit_size) |
479 | | }; |
480 | 361 | let loc = match value.offset { |
481 | | None => { |
482 | 349 | let loc = Location::from_model(bit_size, last_bit_offset); |
483 | 349 | last_bit_offset += bit_size; |
484 | 349 | loc |
485 | | } |
486 | 12 | Some(v) => match v.relative_to { |
487 | | None => { |
488 | 6 | let start_bits = v.bits.unwrap_or(0); |
489 | 6 | let end_bits = start_bits + bit_size; |
490 | 6 | if end_bits > last_bit_offset { Branch (490:24): [True: 0, False: 6]
Branch (490:24): [Folded - Ignored]
|
491 | 0 | last_bit_offset = end_bits; |
492 | 6 | } |
493 | 6 | Location::from_model(bit_size, start_bits) |
494 | | } |
495 | 6 | Some(name) => { |
496 | 36 | let field6 = fields.iter()6 .find6 (|v| v.name == name).ok_or6 (Error::UndefinedReference(name)6 )?0 ; |
497 | 6 | let start_bits = field.loc.bit_offset + v.bits.unwrap_or(0); |
498 | 6 | let end_bits = start_bits + bit_size; |
499 | 6 | if end_bits > last_bit_offset { Branch (499:24): [True: 0, False: 6]
Branch (499:24): [Folded - Ignored]
|
500 | 0 | last_bit_offset = end_bits; |
501 | 6 | } |
502 | 6 | Location::from_model(bit_size, start_bits) |
503 | | } |
504 | | }, |
505 | | }; |
506 | 361 | Ok(( |
507 | 361 | Self { |
508 | 361 | name: value.name, |
509 | 361 | ty, |
510 | 361 | loc, |
511 | 361 | description: value.description, |
512 | 361 | }, |
513 | 361 | last_bit_offset, |
514 | 361 | )) |
515 | 369 | } |
516 | | } |
517 | | |
518 | | #[derive(Clone, Debug)] |
519 | | pub struct Structure { |
520 | | pub name: String, |
521 | | pub description: Option<Description>, |
522 | | pub fields: Vec<Field>, |
523 | | pub byte_size: usize, |
524 | | pub bit_size: usize, |
525 | | used_in_header: Cell<bool>, |
526 | | } |
527 | | |
528 | | impl Structure { |
529 | 26 | pub fn set_used_in_header(&self) { |
530 | 26 | self.used_in_header.set(true); |
531 | 26 | } |
532 | | |
533 | 120 | pub fn is_used_in_header(&self) -> bool { |
534 | 120 | self.used_in_header.get() |
535 | 120 | } |
536 | | |
537 | 196 | pub fn from_model(proto: &Protocol, value: crate::model::structure::Structure) -> Result<Structure, Error> { |
538 | 196 | let mut fields = Vec::with_capacity(value.fields.len()); |
539 | 196 | let mut last_bit_offset = 0; |
540 | 557 | for field369 in value.fields { |
541 | 369 | let (field361 , new_offset361 ) = Field::from_model(proto, &fields, last_bit_offset, field)?8 ; |
542 | 361 | fields.push(field); |
543 | 361 | last_bit_offset = new_offset; |
544 | | } |
545 | 188 | let s = Structure { |
546 | 188 | name: value.name, |
547 | 188 | description: value.description, |
548 | 188 | fields, |
549 | 188 | bit_size: last_bit_offset, |
550 | 188 | byte_size: if last_bit_offset % 8 != 0 { Branch (550:27): [True: 0, False: 188]
Branch (550:27): [Folded - Ignored]
|
551 | 0 | (last_bit_offset / 8) + 1 |
552 | | } else { |
553 | 188 | last_bit_offset / 8 |
554 | | }, |
555 | 188 | used_in_header: Cell::new(false), |
556 | | }; |
557 | 188 | if s.bit_size == 0 { Branch (557:12): [True: 1, False: 187]
Branch (557:12): [Folded - Ignored]
|
558 | 1 | return Err(Error::ZeroStruct); |
559 | 187 | } |
560 | 187 | Ok(s) |
561 | 196 | } |
562 | | } |
563 | | |
564 | | name_index!(Structure => name); |